React Hooks目前是 React 处于提案阶段的一个特性, 根据其官方的介绍, Hooks被创建出来主要动机如下:
跨组件复用stateful logic(包含状态的逻辑)十分困难
复杂的组件难以理解
Hooks让React组件也是更接近于函数
很多时候组件之间的逻辑都是相似的, 如果想复用组件中的逻辑 或者扩展组件的逻辑, 我们可以通过 render props 或者高阶组件, 所以我们在使用很多开源的组件时, 可以经常看到组件支持传入一个 函数作为 props. 通过这个方式, 我们甚至可以完全重新定义组件的具体渲染
使用 render props 和 stateless component
1 | import React, { PureComponent } from "react"; |
在真实的项目中, 一个组件的场景会比上述复杂的多, 可能需要拆分成非常多的子组件, 改造成本也比较高. 当项目中比较复杂的组件代码都改造为多个小的 stateless 组件, 并通过 render props 和 高阶组件的方式进行组装, 组件的可扩展性和代码的可复用性将会极大的提高.
本来只是想复用组件中的代码逻辑, 最后却重构整个组件, React 团队认为这种现象也指出了一些更深层次的问题:React需要一些更好的底层元素来复用stateful logic.
使用 React Hooks实现上述的功能1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import React, { useState } from "react";
const ListItemComponent = (props = {}) => {
const [isSelected, setIsSelected] = useState(false);
const { value } = props;
return (
<li onClick={() => setIsSelected(!isSelected)}>
<span>{value}</span>
{isSelected ? "已选择" : ""}
</li>
);
};
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const App = () => {
return (
<>
demo 6_2:
<br />
{data.map(item => (
<ListItemComponent value={item} />
))}
</>
);
};
export default App;
从上面使用 React Hooks改造过的代码中, 可以直观的看到, 在ListItemComponent里面可以直接创建一个 值 和 修改值的方法, 就不用像 render props那样子需要把 “值 和 修改值的方法” 从父组件 一层层的传递到子组件. 利用useState这个 hooks, 等同于把依赖的状态数据注入组件, 只是这些数据并非是集中管理的, 而是分散且粒度更细的数据, 关于数据共享 和 数据修改, 还有useReducer 和 useContext 等hooks可以提供能力支持
React hooks 只是逻辑的复用, 并非数据的复用
1 | import React, { useState } from "react"; |
上述的 List1 List2 都复用 useIsSelected, 但是只是逻辑的复用, 实际上会创建两个独立的值, 互不干扰.
React hooks 本质上只是数组
React Hooks 带来两个使用上的约定:
- 不要在循环,条件判断,嵌套函数里面调用 Hooks
- 只在 React 的函数里面调用 Hooks
其实很好理解, 每次使用 useXXX Hooks的时候, 是通过两个数组来存储对应的 值 和修改值的方法, 原理详细参考
React Hooks 这部分就草草的收尾了, 一方面是这块确实没有太多的实践经验, 纯属是在理论上做简单的分析与介绍, 更多的 Hooks 细节介绍由于有 官方文档, 就不重复阐述,
React Hooks 部分也可以参考: 精读《React Hooks》